package com.yiren.dbaa.module.exam.view.activity;

import android.os.CountDownTimer;
import android.os.Handler;
import android.text.TextUtils;
import android.view.KeyEvent;

import com.google.gson.Gson;
import com.yiren.backstage.config.api.LoadConfigApi;
import com.yiren.backstage.config.bean.device.PracticeCarCheckConfigBean;
import com.yiren.backstage.config.bean.device.UserParamConfigBean;
import com.yiren.backstage.config.enums.SiteConfigCodeEnum;
import com.yiren.backstage.currency.bean.CarStateBean;
import com.yiren.backstage.currency.bean.GpsInfoBean;
import com.yiren.backstage.currency.bean.LinePointBean;
import com.yiren.backstage.currency.bean.VoiceBean;
import com.yiren.backstage.currency.constant.SignalGConstant;
import com.yiren.backstage.currency.entity.GradeStandardEntity;
import com.yiren.backstage.currency.entity.LineInfoEntity;
import com.yiren.backstage.currency.entity.ProjectEntity;
import com.yiren.backstage.currency.entity.SiteEntity;
import com.yiren.backstage.currency.enums.CarStateValueEnum;
import com.yiren.backstage.currency.enums.ProjectTypeEnum;
import com.yiren.backstage.currency.enums.TaskStateEnum;
import com.yiren.backstage.currency.utils.DateUtil;
import com.yiren.backstage.currency.utils.StringUtil;
import com.yiren.backstage.db.dao.controller.UserDbController;
import com.yiren.backstage.judge.api.IExamJudge;
import com.yiren.backstage.judge.api.IExamStateCallBack;
import com.yiren.backstage.judge.api.impl.ExamJudgeApiImpl;
import com.yiren.backstage.player.announcer.QueueMediaPlayer;
import com.yiren.backstage.player.announcer.SingleMediaPlayer;
import com.yiren.dbaa.activity.BaseActivity;
import com.yiren.dbaa.constant.NumberConstant;
import com.yiren.dbaa.constant.PointCode;
import com.yiren.dbaa.constant.SendParamConstant;
import com.yiren.dbaa.constant.StringConstant;
import com.yiren.dbaa.currency.api.CommonCallBack;
import com.yiren.dbaa.module.exam.api.IExamGradeApi;
import com.yiren.dbaa.module.exam.api.IExamLineApi;
import com.yiren.dbaa.module.exam.api.IExamProjectApi;
import com.yiren.dbaa.module.exam.api.IExamRecordApi;
import com.yiren.dbaa.module.exam.api.IExamViewApi;
import com.yiren.dbaa.module.exam.api.OnSelectLineSureListener;
import com.yiren.dbaa.module.exam.api.impl.ExamGradeApiImpl;
import com.yiren.dbaa.module.exam.api.impl.ExamLineApiImpl;
import com.yiren.dbaa.module.exam.api.impl.ExamProjectApiImpl;
import com.yiren.dbaa.module.exam.api.impl.ExamRecordApiImpl;
import com.yiren.dbaa.module.exam.api.impl.ExamViewApiImpl;
import com.yiren.dbaa.module.exam.bean.DriveDataBean;
import com.yiren.dbaa.module.exam.bean.DriveEndJsonBean;
import com.yiren.dbaa.module.exam.bean.DriveRecordBean;
import com.yiren.dbaa.module.exam.bean.DriveStartJsonBean;
import com.yiren.dbaa.module.exam.bean.ExamGradeBean;
import com.yiren.dbaa.module.exam.bean.GradeDetailsBean;
import com.yiren.dbaa.module.exam.bean.record.ExecutingPointBean;
import com.yiren.dbaa.module.exam.view.adapter.DjProjectInfoAdapter;
import com.yiren.dbaa.module.exam.view.dialog.ExamSelectDialog;
import com.yiren.dbaa.module.exam.view.dialog.LineChooseDialog;
import com.yiren.dbaa.module.exam.view.id.ExamMapId;
import com.yiren.dbaa.module.exam.view.id.ExamStudentId;
import com.yiren.dbaa.module.practice_set.site.bean.ExamMerge;
import com.yiren.dbaa.util.DoubleClickUtils;
import com.yiren.dbaa.view.dialog.LoadDialog;
import com.yiren.dbaa.view.toast.MessageBox;

import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by WANGRONGXIANG
 * on 2022/2/25
 * Describe 考试页面父类
 */
public abstract class BaseExamActivity extends BaseActivity implements DjProjectInfoAdapter.OnProjectClickListener {

    protected IExamViewApi iExamViewApi;      //页面view处理接口类
    protected IExamProjectApi iExamProjectApi;//页面项目处理接口类
    protected IExamLineApi iExamLineApi;      //页面线路处理接口类
    protected IExamGradeApi iExamGradeApi;    //练车评分处理接口类
    protected IExamJudge iExamJudge;          //考试评判线程
    protected IExamRecordApi iExamRecordApi;  //练车记录处理类

    protected ExamStudentId idStudent;        //通用学员模型
    protected ExamMapId idMap;                //通用地图id模型

    protected PracticeCarCheckConfigBean practiceCarCheckConfig;//考试参数配置对象
    protected UserParamConfigBean userParamConfig;

    protected Runnable stateInfoRunnable;         //状态信息线程类
    protected Handler stateHandler = new Handler();

    protected List<ProjectEntity> lightProjects;  //科三灯光项目列表
    protected List<ProjectEntity> projects;       //科三白天项目列表
    protected List<LineInfoEntity> lineInfos;     //线路信息列表
    protected ProjectEntity fullJudgeProject;     //全程评判点位
    protected ProjectEntity startProjectInfo;     //起始点位信息
    protected LineInfoEntity lineInfo;            //当前操作线路
    private ProjectEntity kbtcProject;            //靠边停车项目
    protected List<GradeStandardEntity> artificialJudges;             //人工评判集合
    protected List<ExamGradeBean> testRecords = new ArrayList<>();   //评分列表
    private List<String> kbtcProjects;           //靠边停车前需要完成的项目

    private Map<String, GradeStandardEntity> realtimeVoices = new LinkedHashMap<>(); //实时语音列表
    private Map<String, GradeStandardEntity> allGradeVoices = new LinkedHashMap<>(); //评分语音总集合,用于结束考试播报
    protected HashMap<String, Integer> projectCodeMap = new HashMap<>();    //记录扣分的项目和该项目所扣分数
    private List<ProjectEntity> executedPoint = new ArrayList<>();        //已经播报过的项目集合
    private List<ExecutingPointBean> executingPoints = new ArrayList<>(); //正在执行的项目点位集合

    protected boolean isStartExamFlag = false;//标示是否开始考试
    protected int totalScore = 100;   //总分
    protected int mode = 1;           //1：白天模式  2：夜间模式
    private String startTime;         //开始练车时间
    private DriveDataBean driveData;  //练车总记录
    private String lineSessionId;     //记录使用线路情况ID
    protected String authId;          //考试授权ID

    protected CountDownTimer downTimer;//考试计时器
    protected float startMileage;      //起始里程
    protected long trainingTime;       //训练时间
    protected float trainingMileage;   //训练里程(米)
    protected float ljStartMileageValue = 0;  //累计里程符合？条件开始值
    protected float jdMileageValue = 0;       //符合?条件时阶段里程
    protected float ljTotalMileageValue = 0;  //里程符合？条件累计距离

    protected Gson gson = new Gson();
    protected String model; //练车模式(自动播报，自动评判)

    /**
     * 子类考试页面初始化时需要调用父类的方法
     */
    public void initParent() {
        iExamViewApi = new ExamViewApiImpl(this);
        iExamProjectApi = new ExamProjectApiImpl(this);
        iExamLineApi = new ExamLineApiImpl(this);
        iExamGradeApi = new ExamGradeApiImpl(this);
        iExamRecordApi = new ExamRecordApiImpl(this);
        iExamJudge = new ExamJudgeApiImpl(this, examStateCallBack);

        idStudent = new ExamStudentId(this);
        idMap = new ExamMapId(this, iExamViewApi);

        practiceCarCheckConfig = LoadConfigApi.loadPracticeCarCheckConfig(this);
        userParamConfig = LoadConfigApi.loadUserParamConfig(this);
        if (null != userParamConfig.getSite()) {
            //这里合并数据重新从UserDb取SiteEntity是因为修改参数没有更新userParamConfig里面的site，所以需要重新读取
            SiteEntity site = (SiteEntity) UserDbController.getInstance(false).queryById(userParamConfig.getSite().getSiteCode(), SiteEntity.class);
            mergeData(site);
        }
        lightProjects = iExamProjectApi.getLightProjects();
        projects = iExamProjectApi.getProjectList();
        lineInfos = iExamLineApi.loadLineInfos();
        fullJudgeProject = iExamProjectApi.loadFullJudgeProject();
        artificialJudges = iExamGradeApi.getArtificialJudges();

        kbtcProject = iExamProjectApi.getKbtcProject(projects);
        startProjectInfo = iExamProjectApi.loadStartPointInfo(practiceCarCheckConfig.getStartExamProject(), lightProjects);
        lineInfo = iExamLineApi.getOneLineInfo(lineInfos);
        idMap.setLineInfo(lineInfo);
        model = getIntent().getStringExtra(SendParamConstant.EXAM_MODEL);
    }

    /**
     * 合并规则参数配置
     */
    protected void mergeData(SiteEntity site) {
        //合并数据
        ExamMerge examMerge = new ExamMerge(this);
        LoadDialog.show(this, "正在加载数据...");
        examMerge.loadExamData(site, new CommonCallBack() {
            @Override
            public void success(Object result) {
                LoadDialog.dismiss(BaseExamActivity.this);
                runOnUiThread(() -> refreshParameter());
            }
        });
    }

    /**
     * 显示线路选择弹框
     */
    public void showLineSelectDialog(OnSelectLineSureListener listener) {
        ExamSelectDialog.getLineSelectDialog(this, lineInfos, lineInfo).setOnLineSelectChangeListener(new LineChooseDialog.OnLineSelectChangeListener() {
            @Override
            public void onLineSelectChange(int position, boolean isChange) {
                if (isChange) {
                    lineInfo = lineInfos.get(position);
                    idMap.setLineInfo(lineInfo);
                }
                listener.onSelectLineSure(isChange);
            }
        });
    }

    /**
     * 计算符合配置？条件的里程
     */
    protected void calConditionMileage(CarStateBean carState) {
        switch (LoadConfigApi.loadSignalSourceConfig(this).getCarType()) {
            case C2_MODEL:
                if (carState.getSpeed() > (int) SignalGConstant.examConfigMap.get(SiteConfigCodeEnum.L26.toString())) {
                    if (ljStartMileageValue == 0) ljStartMileageValue = trainingMileage;
                    jdMileageValue = (trainingMileage - ljStartMileageValue);
                } else {
                    if (ljStartMileageValue != 0) ljTotalMileageValue += jdMileageValue;
                    ljStartMileageValue = 0;
                    jdMileageValue = 0;
                }
                break;
            default:
                int chooseValueC1 = (int) SignalGConstant.examConfigMap.get(SiteConfigCodeEnum.L21.toString());
                if ((chooseValueC1 == 1 && carState.getSpeed() > (int) SignalGConstant.examConfigMap.get(SiteConfigCodeEnum.L22.toString()))
                        || (chooseValueC1 == 2 && (carState.getGear() == CarStateValueEnum.ONE_GEAR || carState.getGear() == CarStateValueEnum.TWO_GEAR))
                        || (chooseValueC1 == 3 && (carState.getSeparationReunion() == CarStateValueEnum.LOOSEN) && (carState.getGear() == CarStateValueEnum.ONE_GEAR || carState.getGear() == CarStateValueEnum.TWO_GEAR))
                        || (chooseValueC1 == 4 && carState.getGear().getValue() >= (int) SignalGConstant.examConfigMap.get(SiteConfigCodeEnum.L23.toString()) && carState.getSpeed() > (int) SignalGConstant.examConfigMap.get(SiteConfigCodeEnum.L24.toString()))
                ) {
                    if (ljStartMileageValue == 0) ljStartMileageValue = trainingMileage;
                    jdMileageValue = (trainingMileage - ljStartMileageValue);
                } else {
                    if (ljStartMileageValue != 0) ljTotalMileageValue += jdMileageValue;
                    ljStartMileageValue = 0;
                    jdMileageValue = 0;
                }
                break;
        }
    }

    /**
     * 开始考试公共方法
     */
    public void startExamPublic() {
        totalScore = 100;
        testRecords.clear();
        realtimeVoices.clear();
        allGradeVoices.clear();
        executedPoint.clear();
        executingPoints.clear();
        ljStartMileageValue = jdMileageValue = ljTotalMileageValue = 0;
        startMileage = CarStateBean.getInstance().getTotalMileage();
        startTime = DateUtil.getLongTimeFormat(System.currentTimeMillis(), DateUtil.FORMAT_ONE);
        lineSessionId = StringUtil.getUUID();
        authId = StringUtil.getUUID();
        if (downTimer == null) createCountDownTime();
        downTimer.start();
        //记录练车记录开始json
        DriveStartJsonBean startJson = new DriveStartJsonBean(idStudent.getStudentBean().getStudent(), authId, startTime, userParamConfig.getSite().getSiteCode(), idStudent.getStudentBean().getCode() == 2 || TextUtils.equals(idStudent.getStudentBean().getStudent(), userParamConfig.getUserInfo().getId().toString()), "3", idStudent.getStudentBean().getCode());
        driveData = new DriveDataBean(authId, userParamConfig.getUserInfo().getId().toString(), gson.toJson(startJson));
        //上传开始练车记录
        DriveRecordBean startRecord = new DriveRecordBean(idMap.isGjdShow() ? "1" : "0", idStudent.getStudentBean().getCode() != 2 ? idStudent.getStudentBean().getStudent() : "", String.valueOf(mode), "0", lineInfo.getId(), lineInfo.getName(), lineSessionId, startTime, userParamConfig.getSite().getSiteCode(), "0");
        iExamRecordApi.uploadStartExamData(startRecord);
        kbtcProjects = iExamProjectApi.getKbtcReqProjects();
        iExamGradeApi.playStartExamVoice(lineInfo, () -> {
            iExamJudge.startExam(startProjectInfo, lineInfo);
            //添加全程评判点位执行
            executingPoints.add(new ExecutingPointBean(fullJudgeProject, new ArrayList<>()));
        });
    }

    /**
     * 结束考试公共方法
     */
    public void endExamPublic() {
        isStartExamFlag = false;
        iExamJudge.endExam();
        new Handler().postDelayed(() -> {
            if (downTimer != null) downTimer.cancel();
            iExamGradeApi.endExamPlayScore(totalScore, allGradeVoices, idStudent.getStudentBean().getCode() == 0);
            idMap.setMapViewScale(0);
            endExamUploadData();
        }, 1000);
    }


    /**
     * 退出考试公共方法
     */
    public void exitExamPublic() {
        if (downTimer != null) downTimer.cancel();
        iExamJudge.exitExam();
        endExamUploadData();
    }

    /**
     * 结束考试上传数据
     */
    private void endExamUploadData() {
        //记录结束练车记录
        String endTime = DateUtil.getLongTimeFormat(System.currentTimeMillis(), DateUtil.FORMAT_ONE);
        List<GradeDetailsBean> useDetailList = new ArrayList<>();
        DriveRecordBean lineUse = new DriveRecordBean(idStudent.getStudentBean().getCode() != 2 ? idStudent.getStudentBean().getStudent() : "", idMap.isGjdShow() ? "1" : "0", String.valueOf(mode), String.valueOf(trainingMileage), lineInfo.getId(), lineInfo.getName(), lineSessionId, startTime, endTime, userParamConfig.getSite().getSiteCode(), String.valueOf(totalScore));
        DriveEndJsonBean endJson = new DriveEndJsonBean(authId, endTime, lineUse, useDetailList);
        for (ExamGradeBean egm : testRecords) {
            GradeStandardEntity gradeStandard = egm.getGradeStandardEntity();
            if (null == gradeStandard) continue;
            useDetailList.add(new GradeDetailsBean(String.valueOf(gradeStandard.getProjectId()), gradeStandard.getProjectEntity().getName(), String.valueOf(gradeStandard.getGrade()), gradeStandard.getStandardContent()));
        }
        driveData.setEndData(System.currentTimeMillis(), gson.toJson(endJson));
        iExamRecordApi.uploadEndExamData(driveData);
        //结束考试，上传正在执行轨迹点位记录
        iExamRecordApi.endExamUploadCarRecord(executingPoints, idMap.isGjdShow(), lineInfo.getId(), lineSessionId, idStudent.getStudentBean().getStudent());
    }

    /**
     * 线程刷新公共处理方法
     */
    public void runnablePublic(CarStateBean carState, GpsInfoBean gps) {
        idMap.updateCarStatus(carState, gps);
        if (isStartExamFlag) {
            idMap.setCurrentStatus(gps);
            //添加练车记录数据
            iExamRecordApi.addPracticeData(executingPoints, carState, gps, idMap);
            if (practiceCarCheckConfig.isRealTimePlayGrade()) {
                if (!QueueMediaPlayer.getInstance().isPlaying() && !SingleMediaPlayer.getInstance().isPlaying() && realtimeVoices.size() > 0) {
                    iExamGradeApi.playGradeVoice(realtimeVoices, (id) -> realtimeVoices.remove(id));
                }
            }
        }
    }

    /**
     * 设置项目状态改变
     */
    public void setProjectStateChange(ProjectEntity projectEntity, TaskStateEnum taskState) {
        //创建或者上传车辆行驶轨迹记录
        iExamRecordApi.create2UploadCarRecord(executingPoints, projectEntity, taskState, idMap, lineInfo.getId(), lineSessionId, idStudent.getStudentBean().getStudent());
        idMap.setCurrentProject(projectEntity, taskState);
        iExamProjectApi.setProjectState(projects, projectEntity, taskState);
        //加载灯光和上车准备后接项目
        ProjectEntity project = iExamProjectApi.loadFollowProject(projectEntity, taskState, lightProjects);
        if (null != project) filterProjectExecute(project);
    }

    /**
     * 项目点击事件回调
     */
    @Override
    public void onProjectClick(int projectPosition) {
        if (isStartExamFlag) {
            ProjectEntity projectEntity = projects.get(projectPosition);
            if (PointCode.YJXS_CODE.equals(String.valueOf(projectEntity.getId()))) {
                if (iExamProjectApi.filterCurProject(idMap.getCurExecuteProject(), projectEntity))
                    return;
                iExamProjectApi.startLightProject(lightProjects, iExamJudge);
            } else {
                filterProjectExecute(projectEntity);
            }
        }
    }

    /**
     * 获取当前项目以及下一个项目
     */
    public void getNextPointInfo(String linePointId) {
        List<LinePointBean> linePoints = lineInfo.getLinePoints();
        for (int i = 0; i < linePoints.size(); i++) {
            if (linePoints.get(i).getLinePointId().equals(linePointId)) {
                idMap.setNextLinePoint(i < linePoints.size() - 1 ? linePoints.get(i + 1) : null);
                break;
            }
        }
    }

    /**
     * 过滤项目执行
     *
     * @return true:执行项目 false:该项目不满足执行条件
     */
    private boolean filterProjectExecute(ProjectEntity projectInfo) {
        if (iExamProjectApi.filterCurProject(idMap.getCurExecuteProject(), projectInfo)) {
            return false;
        }
        boolean isLocked;
        if (projectInfo.getName().contains("靠边停车")) { //判断项目是否被锁定
            isLocked = iExamProjectApi.isLockedKbtcProject(trainingMileage, kbtcProjects);
        } else {  //判断项目是否被锁定
            isLocked = iExamProjectApi.isLockedProjectEntity(projectInfo, executedPoint);
        }
        if (!isLocked) {
            executedPoint.add(projectInfo);
            if (kbtcProjects.contains(projectInfo.getId()))
                kbtcProjects.remove(projectInfo.getId());
            iExamJudge.startProjectJudge(projectInfo);
            return true;
        }
        return false;
    }

    /**
     * 创建计时器，用来计算练车时间
     */
    public void createCountDownTime() {
        if (downTimer == null) {
            downTimer = new CountDownTimer(NumberConstant.MILLIS_IN_FUTURE, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {
                    if (!isStartExamFlag) {
                        this.cancel();
                        trainingTime = 0;
                        trainingMileage = 0;
                    } else {
                        trainingTime = NumberConstant.MILLIS_IN_FUTURE - millisUntilFinished;
                        trainingMileage = (CarStateBean.getInstance().getTotalMileage() - startMileage) / 1000;
                        if (trainingMileage < 0) {
                            startMileage = CarStateBean.getInstance().getTotalMileage();
                        }
                        if (iExamProjectApi.autoExecuteKbtc(idMap.getCurExecuteProject(), kbtcProjects, trainingMileage))
                            if (null != kbtcProject) {
                                iExamJudge.startProjectJudge(kbtcProject);
                            }
                    }
                }

                @Override
                public void onFinish() {

                }
            };
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        removeStateRunnable();
    }

    /**
     * 移除页面状态刷新线程
     */
    public void removeStateRunnable() {
        if (null != stateInfoRunnable) {
            stateHandler.removeCallbacks(stateInfoRunnable);
        }
    }

    /**
     * 添加评分语音
     */
    public void addGradeRecord(GradeStandardEntity gradeStandardEntity) {
        String key = StringUtil.getUUID();
        if (null == gradeStandardEntity.getProjectId()) {
            gradeStandardEntity.setProjectId(PointCode.YJXS_CODE);
            gradeStandardEntity.getProjectEntity().setName(StringConstant.LIGHT_SIMULATION);
            gradeStandardEntity.getProjectEntity().setProjectType(ProjectTypeEnum.LIGHT.toString());
        } else if (gradeStandardEntity.getProjectEntity().getProjectType().equals(ProjectTypeEnum.LIGHT.toString())) {
        } else if (idStudent.getStudentBean().getCode() != 0 && practiceCarCheckConfig.isRealTimePlayGrade()) {
            //如果不是免费播报，并且实时播报评分，则添加实时语音
            realtimeVoices.put(key, gradeStandardEntity);
        }
        projectCodeMap.put(gradeStandardEntity.getProjectId(), iExamGradeApi.getProjectGrade(projectCodeMap, gradeStandardEntity));
        testRecords.add(0, new ExamGradeBean(key, new Date(), gradeStandardEntity));
        allGradeVoices.put(key, gradeStandardEntity);
        //添加练车评分记录
        iExamRecordApi.addCarGradeRecord(key, gradeStandardEntity, executingPoints);
        if (SingleMediaPlayer.getInstance().isPlaying()) realtimeVoices.clear();
        totalScore -= gradeStandardEntity.getGrade();
    }

    /**
     * 删除评分记录
     */
    public void deleteGradeRecord(int position) {
        if (position < testRecords.size()) {
            String key = testRecords.get(position).getId();
            GradeStandardEntity gradeStandardEntity = testRecords.get(position).getGradeStandardEntity();
            totalScore += gradeStandardEntity.getGrade();
            iExamRecordApi.deleteGradeRecord(gradeStandardEntity.getProjectId(), key, executingPoints);
            iExamGradeApi.resetProjectCode(gradeStandardEntity, projectCodeMap);
            testRecords.remove(position);
            realtimeVoices.remove(key);
            allGradeVoices.remove(key);
        }
    }

    /**
     * 考试项目状态改变和添加评分的回调函数
     */
    private IExamStateCallBack examStateCallBack = new IExamStateCallBack() {
        @Override
        public void projectState(ProjectEntity projectEntity, TaskStateEnum taskState) {
            if (isStartExamFlag) { //考试中才改变项目状态
                setProjectStateChange(projectEntity, taskState);
                runOnUiThread(() -> refreshProjectState());
            }
        }

        @Override
        public void addGradeStandard(GradeStandardEntity gradeStandardEntity) {
            if (isStartExamFlag) {
                addGradeRecord(gradeStandardEntity);
                runOnUiThread(() -> refreshGradeState());
            }
        }

        @Override
        public void endExam() {
            runOnUiThread(() -> endExamRefreshState());
        }

        @Override
        public void autoPlayProject(LinePointBean linePoint) {
            ProjectEntity projectInfo = linePoint.getProjectInfo();
            if (filterProjectExecute(projectInfo)) { //如果线路点位没有被过滤掉，则获取下一个需要执行的线路点位
                getNextPointInfo(linePoint.getLinePointId());
            }
        }

        @Override
        public void zxxsDeflectionDistance(int distance) {  //设置直线行驶偏转距离
            if (idMap.getDeflectDistance() == 0) {
                idMap.setDeflectDistance(distance);
            }
            idMap.setDeflectDistance(distance - idMap.getDeflectDistance() > 0 ? distance : -distance);
        }

        @Override
        public void zxxsDeflectionAngle(int angle) {  //设置直线行驶偏转角度
            idMap.setDeflectAngle(angle);
        }

        @Override
        public void playProjectVoice(VoiceBean voiceFile) { //设置项目语音文本
            if (null != voiceFile && StringUtils.isNotEmpty(voiceFile.getVoiceContent())) {
                iExamRecordApi.setVoiceTxt(voiceFile.getVoiceContent());
            }
        }
    };

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (isStartExamFlag) {
                if (DoubleClickUtils.isFastClick()) {
                    finish();
                } else {
                    MessageBox.show(this, "再按一次退出程序");
                }
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    /***
     * 根据获取参数刷新页面显示
     */
    public abstract void refreshParameter();

    /**
     * 刷新项目状态
     */
    public abstract void refreshProjectState();

    /**
     * 刷新评分相关状态
     */
    public abstract void refreshGradeState();

    /**
     * 结束考试刷新状态
     */
    public abstract void endExamRefreshState();
}
